﻿using SciSmtCamLib;
using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace LD
{
    public class SciHelper
    {
        private SciEngine m_engine;
        private ManualResetEvent resetEvent = new ManualResetEvent(true);

        private static SciHelper instance;
        private static object locker = new object();
        public SciHelper()
        {
            m_engine = new SciEngine();
        }
        public SciEngine GetSci { get { return m_engine; } }
        public static SciHelper Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (locker)
                    {
                        if (instance == null)
                        {
                            instance = new SciHelper();
                        }
                    }
                }
                return instance;
            }
        }

        public IntPtr Pic_LeftUp;
        public IntPtr Pic_RightUp;
        public IntPtr Pic_LeftDown;
        public IntPtr Pic_RightDown;
        public IntPtr Pic_Side;

        public void Init()
        {
            LogHelper.Instance.CCD("CCD初始化");
            //初始化Sci程序
            m_engine.InitEngine();
            m_engine.OnAppStart += OnAppStart;
            m_engine.OnAppEnd += OnAppEnd;
            m_engine.OnOperatorStart += OnOperatorStart;
            m_engine.OnOperatorEnd += OnOperatorEnd;
            LogHelper.Instance.CCD("CCD初始化完成");
        }

        /// <summary>
        /// 运行方案时，回调函数
        /// </summary>
        void OnAppStart()
        {
            Console.WriteLine("run project...");
        }
        /// <summary>
        /// 停止方案时，回调函数
        /// </summary>
        void OnAppEnd()
        {
            Console.WriteLine("stop project!");
        }
        /// <summary>
        /// 算子开始前，回调函数
        /// </summary>
        /// <param name="blockName"></param>
        /// <param name="oprName"></param>
        void OnOperatorStart(string blockName, string oprName)
        {
            Console.WriteLine("before operator Execute!");
        }
        /// <summary>
        /// 方案结束时，回调函数
        /// </summary>
        /// <param name="blockName"></param>
        /// <param name="oprName"></param>
        void OnOperatorEnd(string blockName, string oprName)
        {
            if (blockName == "camera1" && oprName == "Location_result")
            {
                //清除m_strRecvSci变量值
                double x = 0;
                double y = 0;
                m_engine.GetVariablePt("center", ref x, ref y);
                //将sci变量中的值，赋值给m_strRecvSci
                //接收数据线程启动
                resetEvent.Set();

            }
            if (blockName == "camera2" && oprName == "measure_result")
            {

                double distance = 0;
                m_engine.GetVariableNumber("distance", ref distance);
                ///接收数据线程启动
                resetEvent.Set();
            }
        }

        /// <summary>
        /// 接受处理数据线程-根据协议进行解析结果
        /// </summary>
        private void RecvDateScithread()
        {

        }

        public void Run()
        {
            m_engine.Run();
        }
        public void Stop()
        {
            //释放事件
            resetEvent.Set();
            //退出线程
            m_engine.Stop();
            //退出释放引擎
            m_engine.ReleaseEngine();
        }

        //延时防止假死状态
        public void Delay(int milliSecond)
        {
            int start = Environment.TickCount;
            while (Math.Abs(Environment.TickCount - start) < milliSecond)
            {
                Application.DoEvents();
            }
        }
        public void Open(string filePath)
        {
            if (!File.Exists(filePath)) return;
            //打开sci方案
            m_engine.OpenProject(filePath);

            //sci窗口1绑定pictureBox1
            int displayWnd1 = 0;
            int displayWnd2 = 0;
            int displayWnd3 = 0;
            int displayWnd4 = 0;
            int displayWnd5 = 0;

            m_engine.ConnectToWindow(1, (int)Pic_LeftUp, displayWnd1);
            m_engine.ConnectToWindow(2, (int)Pic_LeftDown, displayWnd2);
            m_engine.ConnectToWindow(3, (int)Pic_RightUp, displayWnd3);
            m_engine.ConnectToWindow(4, (int)Pic_RightDown, displayWnd4);
            m_engine.ConnectToWindow(5, (int)Pic_Side, displayWnd5);


            //指定算子在运行结束后执行回调函数，注意:该函数一般在打开方案后执行的，否则当前方案没有执行的
            //m_engine.EnableOperatorEvent("camera1", "Location_result", SciCamOperatorEvent.SCICAM_OPR_RUN_END);
            //m_engine.EnableOperatorEvent("camera2", "measure_result", SciCamOperatorEvent.SCICAM_OPR_RUN_END);
            m_engine.Run();

        }
        public void ChangePartNo(string ccdName)
        {
            string filePath = Path.Combine(Appbus.BasePath, "CCD");
            filePath = Path.Combine(filePath, ccdName);
            Open(filePath);
        }
        /// <summary>
        /// 找圆
        /// </summary>
        public void FindCircleSetting()
        {
            SciImage img = new SciImage();
            //获取图片导入图像来源，或者是采集图像来源
            m_engine.GetMeasurementImage("camera1", "importImage_1", "Image", ref img);
            //显示找直线参数对话框
            m_engine.ShowSettingWindow("camera1", "FindCircle_1", ref img);
        }
        /// <summary>
        /// 卡尺参数
        /// </summary>
        public void CalliperSetting()
        {
            SciImage img = new SciImage();
            //获取图片导入图像来源，或者是采集图像来源
            m_engine.GetMeasurementImage("camera2", "importImage_1", "Image", ref img);
            //显示找直线参数对话框
            m_engine.ShowSettingWindow("camera2", "Calliper_1", ref img);
        }

        public bool 标定(string module, string point, string ccdname, string bdcommand, ushort axisX, ushort axisY)
        {
            LogHelper.Instance.CCD($"【{module}】开始标定");

            float[] calib_x = new float[9] { 0, 2, 0, -2, -2, 0, 0, 2, 2 };
            float[] calib_y = new float[9] { 0, 0, -2, 0, 0, 2, 2, 0, 0 };

            ushort axisXId = axisX;
            ushort axisYId = axisY;

            //9点
            for (int i = 0; i < calib_x.Length; i++)
            {
                //相对移动
                //BcFactory.Instance.Control.Move_Ration(axisXId, calib_x[i], (int)Cache.GetCache(CONST.MANUAL_SPEED));
                //BcFactory.Instance.Control.Move_Ration(axisYId, calib_y[i], (int)Cache.GetCache(CONST.MANUAL_SPEED));
                //BcFactory.Instance.Control.WaitAxisComplete(axisXId);
                //BcFactory.Instance.Control.WaitAxisComplete(axisYId);
                //Get世界坐标
                double x =0;
                double y = 0;
                //拍照
                var result = TcpIpService.Instance[ccdname].Send($"{bdcommand},{x},{y},{i}").ToString();
                if (result.IndexOf("OK") >= 0)
                {
                }
                else
                {
                    LogHelper.Instance.Warr($"【{ccdname}】相机标定失败");
                    LogHelper.Instance.CCD($"【{module}】标定失败");
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 侧方相机检测
        /// </summary>
        /// <returns></returns>
        public bool SideCheck(string ccdName)
        {
            if (!Appbus.Ccd_Enabled)
                return true;
            var result = TcpIpService.Instance[ccdName].Send($"T1").ToString();
            LogHelper.Instance.CCD($"【{ccdName}】侧相机返回:{result}");
            if (result == "T1,1")
                return true;
            else
                return false;
        }
        /// <summary>
        /// B轨下相机拍照
        /// </summary>
        /// <returns></returns>
        public bool B_DownCCD_Photo()
        {
            if (!Appbus.Ccd_Enabled)
                return true;
            Cache.SetCache(CONST.B_Down_OFFSET_X, 0.0);
            Cache.SetCache(CONST.B_Down_OFFSET_Y, 0.0);
            int color = (int)Cache.GetCache(CONST.B轨_COLOR);
            var result = TcpIpService.Instance["B轨_CCD"].Send($"T2," + color).ToString();
            LogHelper.Instance.CCD($"【B轨_CCD】下相机返回:{result}");
            string[] array = result.Split(',');

            //if (result == "T2,1")
            //    return true;
            //else
            //    return false;

            if (array.Length > 0 && array[0] == "T2")
            {
                if (array[1] == "1" && double.TryParse(array[2], out var x) && double.TryParse(array[3], out var y))
                {
                    Cache.SetCache(CONST.B_Down_OFFSET_X, x);
                    Cache.SetCache(CONST.B_Down_OFFSET_Y, y);
                    return true;
                }
                else
                {
                    LogHelper.Instance.Warr($"【B轨_CCD】下相机" + result);
                    return false;
                }
            }
            else
            {
                LogHelper.Instance.Warr($"【B轨_CCD】下相机可能超时");
                return false;
            }
        }
        /// <summary>
        /// A轨下相机拍照
        /// </summary>
        /// <returns></returns>
        public bool A_DownCCD_Photo()
        {
            if (!Appbus.Ccd_Enabled)
                return true;
            Cache.SetCache(CONST.A_Down_OFFSET_X, 0.0);
            Cache.SetCache(CONST.A_Down_OFFSET_Y, 0.0);
            int color = (int)Cache.GetCache(CONST.A轨_COLOR);
            var result = TcpIpService.Instance["A轨_CCD"].Send($"T4," + color).ToString();
            LogHelper.Instance.CCD($"【A轨_CCD】下相机返回:{result}");
            string[] array = result.Split(',');

            //if (result == "T4,1")
            //    return true;
            //else
            //    return false;

            if (array.Length > 0 && array[0] == "T4")
            {
                if (array[1] == "1" && double.TryParse(array[2], out var x) && double.TryParse(array[3], out var y))
                {
                    Cache.SetCache(CONST.A_Down_OFFSET_X, x);
                    Cache.SetCache(CONST.A_Down_OFFSET_Y, y);
                    return true;
                }
                else
                {
                    LogHelper.Instance.Warr($"【A轨_CCD】下相机" + result);
                    return false;
                }
            }
            else
            {
                LogHelper.Instance.Warr($"【A轨_CCD】下相机可能超时");
                return false;
            }
        }
        /// <summary>
        /// B轨上相机拍照
        /// </summary>
        /// <remarks>相机反馈相对坐标</remarks>
        /// <returns></returns>
        public bool B_UpCCD_Offset(int index)
        {
            Cache.SetCache(CONST.B_Up_OFFSET_X, 0.0);
            Cache.SetCache(CONST.B_Up_OFFSET_Y, 0.0);

            LogHelper.Instance.CCD($"【B轨_CCD】上相机请求:T3,{index}");
            var result = TcpIpService.Instance["B轨_CCD"].Send($"T3,{index}").ToString();
            LogHelper.Instance.CCD($"【B轨_CCD】上相机返回:{result}");
            string[] array = result.Split(',');
            if (array.Length > 0 && array[0] == "T3")
            {

                if (array[1] == "1" && double.TryParse(array[2], out var x) && double.TryParse(array[3], out var y))
                {
                    LogHelper.Instance.Info($"【B轨_CCD】上相机" + result);
                    Cache.SetCache(CONST.A_Up_OFFSET_X, x);
                    Cache.SetCache(CONST.A_Up_OFFSET_Y, y);
                    return true;
                }
                else
                {
                    LogHelper.Instance.Warr($"【B轨_CCD】上相机" + result);
                    return false;
                }
            }
            else
            {
                LogHelper.Instance.Warr($"【B轨_CCD】上相机可能超时");
                return false;
            }
        }
        /// <summary>
        /// B轨上相机拍照
        /// </summary>
        /// <remarks>相机反馈绝对坐标</remarks>
        /// <param name="index"></param>
        /// <returns></returns>
        public bool B_UpCCD_Abs(int index, string barcode)
        {
            if (!Appbus.Ccd_Enabled)
                return true;

            Cache.SetCache(CONST.B_Up_OFFSET_X, 0.0);
            Cache.SetCache(CONST.B_Up_OFFSET_Y, 0.0);

            double? axis_x_point =0;
            double? axis_y_point = 0; 

            LogHelper.Instance.CCD($"【B轨_CCD】上相机请求:T3,{index},{axis_x_point},{axis_y_point},{barcode}");
            var result = TcpIpService.Instance["B轨_CCD"].Send($"T3,{index},{axis_x_point},{axis_y_point},{barcode}").ToString();
            LogHelper.Instance.CCD($"【B轨_CCD】上相机返回:{result}");
            string[] array = result.Split(',');
            if (array.Length > 0 && array[0] == "T3")
            {

                if (array[1] == "1" && double.TryParse(array[2], out var x) && double.TryParse(array[3], out var y))
                {
                    LogHelper.Instance.Info($"【B轨_CCD】上相机" + result);
                    Cache.SetCache(CONST.B_Up_OFFSET_X, x);
                    Cache.SetCache(CONST.B_Up_OFFSET_Y, y);
                    return true;
                }
                else
                {
                    LogHelper.Instance.Warr($"【B轨_CCD】上相机" + result);
                    return false;
                }
            }
            else
            {
                LogHelper.Instance.Warr($"【B轨_CCD】上相机可能超时");
                return false;
            }
        }
        /// <summary>
        /// A轨上相机拍照
        /// </summary>
        /// <remarks>相机相对坐标</remarks>
        /// <returns></returns>
        public bool A_UpCCD_Offset(int index)
        {
            Cache.SetCache(CONST.A_Up_OFFSET_X, 0.0);
            Cache.SetCache(CONST.A_Up_OFFSET_Y, 0.0);

            LogHelper.Instance.CCD($"【A轨_CCD】上相机请求:T5,{index}");
            var result = TcpIpService.Instance["A轨_CCD"].Send($"T5,{index}").ToString();
            LogHelper.Instance.CCD($"【A轨_CCD】上相机返回:{result}");
            string[] array = result.Split(',');
            if (array.Length > 0 && array[0] == "T5")
            {
                if (array[1] == "1" && double.TryParse(array[2], out var x) && double.TryParse(array[3], out var y))
                {
                    LogHelper.Instance.Info($"【A轨_CCD】上相机" + result);
                    Cache.SetCache(CONST.A_Up_OFFSET_X, x);
                    Cache.SetCache(CONST.A_Up_OFFSET_Y, y);
                    return true;
                }
                else
                {
                    LogHelper.Instance.Warr($"【A轨_CCD】上相机" + result);
                    return false;
                }
            }
            else
            {
                LogHelper.Instance.Warr($"【A轨_CCD】上相机可能超时");
                return false;
            }
        }
        /// <summary>
        /// A轨上相机拍照
        /// </summary>
        /// <remarks>相机返回绝对坐标</remarks>
        /// <param name="index"></param>
        /// <returns></returns>
        public bool A_UpCCD_Abs(int index, string barcode)
        {
            if (!Appbus.Ccd_Enabled)
                return true;
            Cache.SetCache(CONST.A_Up_OFFSET_X, 0.0);
            Cache.SetCache(CONST.A_Up_OFFSET_Y, 0.0);
          
            double? axis_x_point = 0;
            double? axis_y_point = 0;
            LogHelper.Instance.CCD($"【A轨_CCD】上相机请求:T5,{index},{axis_x_point},{axis_y_point},{barcode}");
            var result = TcpIpService.Instance["A轨_CCD"].Send($"T5,{index},{axis_x_point},{axis_y_point},{barcode}").ToString();
            LogHelper.Instance.CCD($"【A轨_CCD】上相机返回:{result}");
            string[] array = result.Split(',');
            if (array.Length > 0 && array[0] == "T5")
            {
                if (array[1] == "1" && double.TryParse(array[2], out var x) && double.TryParse(array[3], out var y))
                {
                    LogHelper.Instance.Info($"【A轨_CCD】上相机" + result);
                    Cache.SetCache(CONST.A_Up_OFFSET_X, x);
                    Cache.SetCache(CONST.A_Up_OFFSET_Y, y);
                    return true;
                }
                else
                {
                    LogHelper.Instance.Warr($"【A轨_CCD】上相机" + result);
                    return false;
                }
            }
            else
            {
                LogHelper.Instance.Warr($"【A轨_CCD】上相机可能超时");
                return false;
            }
        }
        public CcdDataModel A_UpCCD_AbsEx(int index, string barcode)
        {
            double? axis_x_point =0;
            double? axis_y_point = 0; 
            LogHelper.Instance.CCD($"【A轨_CCD】上相机请求:T5,{index},{axis_x_point},{axis_y_point},{barcode}");
            var result = TcpIpService.Instance["A轨_CCD"].Send($"T5,{index},{axis_x_point},{axis_y_point},{barcode}").ToString();
            LogHelper.Instance.CCD($"【A轨_CCD】上相机返回:{result}");
            string[] array = result.Split(',');
            if (array.Length > 0 && array[0] == "T5")
            {
                if (array[1] == "1" && double.TryParse(array[2], out var x) && double.TryParse(array[3], out var y))
                {
                    LogHelper.Instance.Info($"【A轨_CCD】上相机" + result);

                    return new CcdDataModel()
                    {
                        X = x,
                        Y = y,
                        Result = true,
                        Point = index
                    };
                }
                else
                {
                    LogHelper.Instance.Warr($"【A轨_CCD】上相机" + result);
                    return null;
                }
            }
            else
            {
                LogHelper.Instance.Warr($"【A轨_CCD】上相机可能超时");
                return null;
            }
        }
        public CcdDataModel B_UpCCD_AbsEx(int index, string barcode)
        {
            double? axis_x_point =0;
            double? axis_y_point = 0;

            LogHelper.Instance.CCD($"【B轨_CCD】上相机请求:T3,{index},{axis_x_point},{axis_y_point},{barcode}");
            var result = TcpIpService.Instance["B轨_CCD"].Send($"T3,{index},{axis_x_point},{axis_y_point},{barcode}").ToString();
            LogHelper.Instance.CCD($"【B轨_CCD】上相机返回:{result}");
            string[] array = result.Split(',');
            if (array.Length > 0 && array[0] == "T3")
            {

                if (array[1] == "1" && double.TryParse(array[2], out var x) && double.TryParse(array[3], out var y))
                {
                    LogHelper.Instance.Info($"【B轨_CCD】上相机" + result);
                    return new CcdDataModel()
                    {
                        X = x,
                        Y = y,
                        Result = true,
                        Point = index
                    };
                }
                else
                {
                    LogHelper.Instance.Warr($"【B轨_CCD】上相机" + result);
                    return null;
                }
            }
            else
            {
                LogHelper.Instance.Warr($"【B轨_CCD】上相机可能超时");
                return null;
            }
        }
    }
}
